#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

#define NUM 1024

#define NONE_FLUSH 0x0
#define LINE_FLUSH 0x1
#define FILL_FLUSH 0x2

typedef struct _MyFILE
{
    int _fileno;
    char _buffer[NUM];
    int _end;
    int _flags;
}MyFILE;

MyFILE *my_fopen(const char *filename, const char *method)
{
    assert(filename);
    assert(method);

    int flags = O_RDONLY;

    if(strcmp(method, "r") == 0)
    {}
    else if(strcmp(method, "r+") == 0)
    {
        flags = O_RDWR;
    }
    else if(strcmp(method, "w") == 0)
    {
        flags = O_WRONLY | O_CREAT | O_TRUNC;
    }
    else if(strcmp(method, "w+") == 0)
    {
        flags = O_RDWR | O_CREAT | O_TRUNC;
    }
    else if(strcmp(method, "a") == 0)
    {
        flags = O_WRONLY | O_CREAT | O_APPEND;
    }
    else if(strcmp(method, "a+") == 0)
    {
        flags = O_RDWR | O_CREAT | O_APPEND;
    }

    int fileno = open(filename, flags, 0666);
    if(fileno < 0) return NULL;

    MyFILE *fp = (MyFILE*)malloc(sizeof(MyFILE));
    fp->_fileno = fileno;
    fp->_flags |= LINE_FLUSH;
    fp->_end = 0;

    return fp;
}

void my_fflush(MyFILE* fp)
{
    assert(fp);

    if(fp->_end > 0)
    {
        write(fp->_fileno, fp->_buffer, fp->_end);
        fp->_end = 0;
        syncfs(fp->_fileno);
    }
}

void my_fwrite(MyFILE* fp, const char* start, int len)
{
    assert(fp);
    assert(start);
    assert(len > 0);

    strncpy(fp->_buffer + fp->_end, start, len);
    fp->_end += len;

    if(fp->_flags & NONE_FLUSH)
    {}
    else if(fp->_flags & LINE_FLUSH)
    {
        if(fp->_end > 0 && fp->_buffer[fp->_end - 1] == '\n')
        {
            // fflush
            write(fp->_fileno, fp->_buffer, fp->_end);
            fp->_end = 0;
            syncfs(fp->_fileno);
        }
    }
    else if(fp->_flags & FILL_FLUSH)
    {}
}

void my_fclose(MyFILE* fp)
{
    my_fflush(fp);
    close(fp->_fileno);
    free(fp);
}

int main()
{
    MyFILE* fp = my_fopen("log.txt", "w");
    if(fp == NULL)
    {
        printf("my_fooen error\n");
        return 1;
    }

    const char *s = "hello my 111\n";
    my_fwrite(fp, s, strlen(s));
}